package org.fas.tween
{
	
	import flash.display.Sprite;
	import flash.events.Event;
	
	import org.fas.utils.FuMath;
	
	public class FTween extends Sprite
	{
		public var cbFrame:Function;
		public var cbHalf:Function;
		public var cbComplete:Function;
		//
		private var targetObject:Object;
		private var props:Array;
		private var startValues:Array;
		private var stopValues:Array;
		//
		private var tweenMode:String;
		private var currentValues:Array;
		private var timeSum:Number = 0;
		private var timeNow:Number = 0;
		public var isRun:Boolean = false;
		//
		public function FTween(){
		}
		public function fixs(_targetObject:Object,_props:Array,_stopValues:Array,_startValues:Array=null,_frameSum:Number=20,_tweenMode:String='EASE_OUT'):void{
			this.clear();
			this.targetObject = _targetObject;
			this.props = _props;
			this.stopValues = _stopValues;
			this.startValues = _startValues;
			this.timeSum = _frameSum;
			this.tweenMode = _tweenMode;
		}
		public function fix(_targetObject:Object,_prop:String,_stopValue:Number,_startValue:Number,_frameSum:Number=20,_tweenMode:String='EASE_OUT'):void{
			this.clear();
			this.targetObject.push(_targetObject);
			this.props.push(_prop);
			this.startValues.push(_startValue);
			this.stopValues.push(_stopValue);
			this.timeSum = _frameSum;
			this.tweenMode = _tweenMode;
		}
		private function clear():void{
			this.targetObject = new Array();
			this.props = new Array();
			this.startValues = new Array();
			this.stopValues = new Array();
		}
		public function start():void{
			stop();
//			trace('start',this.startValues);
			if(this.startValues==null){
				this.startValues = new Array();
				for(var i:int=0;i<this.props.length;i++){
					this.startValues.push(this.targetObject[props[i]]);
				}
			}else{
			}
			this.currentValues = this.startValues;
			timeNow = 0;
			isRun = true;
			this.addEventListener(Event.ENTER_FRAME,framehandle);
		}
		private function countValue(_v:*):Number{
			if(_v is Function){
				return (_v as Function)() as Number;
			}else if(_v is Number){
				return _v
			}else{
				throw(new Error('Value Type Error'));
			}
		}
		private function framehandle(_e:Event=null):void{
			timeNow++;
//			trace('startValues[i]',startValues[i]);
			var lastValues:Array = this.currentValues;
			//sin    quick - slow
			var i:int;
			switch(tweenMode){
				case FTweenMode.EASE_OUT:
					for(i=0;i<this.props.length;i++){
						this.currentValues[i] = startValues[i] + (this.countValue(stopValues[i]) - startValues[i])*FuMath.sin(90/timeSum*timeNow);
					}
					break;
				case FTweenMode.EASE_IN:
					for(i=0;i<this.props.length;i++){
						this.currentValues[i] = this.countValue(stopValues[i]) - (this.countValue(stopValues[i]) - startValues[i])*FuMath.cos(90/timeSum*timeNow);
					}
					break;
				case FTweenMode.NORMAL:
					for(i=0;i<this.props.length;i++){
//						trace(this.countValue(stopValues[i]) , startValues[i],timeSum,timeNow);
						this.currentValues[i] = (this.countValue(stopValues[i]) - startValues[i])/timeSum*timeNow+startValues[i];
					}
					break;
			}
			if(timeNow == timeSum){
				complete();
			}else{
				if(timeNow==int(timeSum*2/4) && cbHalf!=null){
					this.cbHalf(this.currentValues[i]);
				}
				for(i=0;i<this.props.length;i++){
//					trace(targetObject,props[i],this.currentValues[i]);
					targetObject[props[i]] = this.currentValues[i];
				}
				if(cbFrame!=null){
					cbFrame(this.currentValues);
				}
			}
		}
		public function stop():void{
			isRun = false;
			this.removeEventListener(Event.ENTER_FRAME,framehandle);
		}
		public function complete():void{
			for(var i:int=0;i<this.props.length;i++){
				this.targetObject[props[i]] = this.countValue(stopValues[i]);
			}
			stop();
			if(this.cbComplete!=null){
				this.cbComplete(this.currentValues);
			}
		}
		public function destory():void{
			this.targetObject = null;
			this.cbComplete = null;
			this.cbFrame = null;
			this.cbHalf = null;
		}
	}
}